<template>
  <lay-container fluid="true" class="user-box lay-watermark-form">
    <lay-watermark content="lay-vue-super" font="20px Microsoft Yahei"
      element-box=".lay-watermark-form"></lay-watermark>
    <lay-card>
      <lay-form style="margin-top: 10px">
        <lay-row>
          <lay-col :md="5">
            <lay-form-item label="用户账号" label-width="80">
              <lay-input v-model="searchQuery.userName" placeholder="请输入" size="sm" :allow-clear="true"
                style="width: 98%"></lay-input>
            </lay-form-item>
          </lay-col>
          <lay-col :md="5">
            <lay-form-item label="用户名" label-width="80">
              <lay-input v-model="searchQuery.nickName" placeholder="请输入" size="sm" :allow-clear="true"
                style="width: 98%"></lay-input>
            </lay-form-item>
          </lay-col>
          <lay-col :md="5">
            <lay-form-item label="性别" label-width="80">
              <lay-select class="search-input" size="sm" v-model="searchQuery.sex" :allow-clear="true"
                placeholder="请选择">
                <lay-select-option value="男" label="男"></lay-select-option>
                <lay-select-option value="女" label="女"></lay-select-option>
              </lay-select>
            </lay-form-item>
          </lay-col>
          <lay-col :md="5">
            <lay-form-item label-width="20">
              <lay-button style="margin-left: 20px" type="primary" size="sm" @click="toSearch">
                查询
              </lay-button>
              <lay-button size="sm" @click="toReset"> 重置 </lay-button>
            </lay-form-item>
          </lay-col>
        </lay-row>
      </lay-form>
    </lay-card>
    <!-- table -->
    <div class="table-box">
      <lay-loading :type="2" :loading="loadingFlag">
        <lay-table :page="page" :height="'100%'" :columns="columns" :loading="loading" :default-toolbar="true"
          :data-source="dataSource" v-model:selected-keys="selectedKeys" @change="change" @sortChange="sortChange">
          <template #status="{ row }">
            <lay-switch :model-value="row.status" @change="changeStatus($event, row)"></lay-switch>
          </template>
          <template #avatar="{ row }">
            <lay-avatar :src="row.avatar"></lay-avatar>
          </template>
          <template v-slot:toolbar>
            <lay-button size="sm" type="primary" @click="editDataLoading('新增')">
              <lay-icon class="layui-icon-addition"></lay-icon>
              新增</lay-button>
            <lay-button size="sm" @click="toRemove">
              <lay-icon class="layui-icon-delete"></lay-icon>
              删除
            </lay-button>
            <lay-button size="sm" @click="toImport">
              <lay-icon class="layui-icon-upload-drag"></lay-icon>
              导入
            </lay-button>
            <lay-button size="sm" @click="getImport">
              <lay-icon class="layui-icon-template-one"></lay-icon>
              下载导入模板
            </lay-button>
          </template>
          <template v-slot:operator="{ row }">
            <lay-button size="xs" type="primary" @click="editDataLoading('编辑', row)">编辑</lay-button>
            <lay-popconfirm content="确定要删除此用户吗?" @confirm="confirm(row)" @cancel="cancel">
              <lay-button size="xs" border="red" border-style="dashed">删除</lay-button>
            </lay-popconfirm>
            <lay-button border="blue" border-style="dashed" @click="openRoleTableLar(row)">分配角色</lay-button>
          </template>
        </lay-table>
      </lay-loading>
    </div>

    <!-- 新增与编辑 -->
    <lay-layer v-model="visible11" :title="title" :area="['1000px', '550px']">
      <div style="padding: 20px">
        <lay-form :model="model11" ref="layFormRef11" required>
          <lay-row space="10">
            <lay-col md="12" sm="12" xs="24">
              <div class="grid-demo"> <lay-form-item label="名称" prop="nickName">
                  <lay-input v-model="model11.nickName" :maxlength="24" placeholder="请输入名称"></lay-input>
                </lay-form-item></div>
            </lay-col>
            <lay-col md="12" sm="12" xs="24">
              <div class="grid-demo"><lay-form-item label="电话" prop="phoneNumber">
                  <lay-input v-model="model11.phoneNumber" :maxlength="11" placeholder="请输入手机号"></lay-input>
                </lay-form-item></div>
            </lay-col>
          </lay-row>
          <lay-row space="10">
            <lay-col md="12" sm="12" xs="24">
              <div class="grid-demo"><lay-form-item label="性别" prop="sex">
                  <lay-select v-model="model11.sex" style="width: 100%">
                    <lay-select-option value="0" label="男"></lay-select-option>
                    <lay-select-option value="1" label="女"></lay-select-option>
                  </lay-select>
                </lay-form-item></div>
            </lay-col>
            <lay-col md="12" sm="12" xs="24">
              <div class="grid-demo"><lay-form-item label="密码" prop="password">
                  <lay-input v-model="model11.password" type="password" password :maxlength="24"
                    placeholder="请输入密码"></lay-input>
                </lay-form-item></div>
            </lay-col>
          </lay-row>

          <lay-row space="10">
            <lay-col md="12" sm="12" xs="24">
              <div class="grid-demo"><lay-form-item label="email" prop="email">
                  <lay-input v-model="model11.email" placeholder="请输入邮箱"></lay-input>
                </lay-form-item></div>
            </lay-col>
            <lay-col md="12" sm="12" xs="24">
              <lay-form-item label="组织部门" prop="deptId">
                  <lay-cascader :options="optionsDeptSelect" v-model="model11.deptId" placeholder="请选择部门" :check-strictly="false"  :lazy="false"
                    allow-clear style="width:100%;"></lay-cascader>
              </lay-form-item>
            </lay-col>
          </lay-row>
          <lay-row space="10">
            <lay-col md="24" sm="24" xs="24">
              <lay-form-item label="描述" prop="remark">
                <lay-textarea placeholder="请输入描述" v-model="model11.remark"></lay-textarea>
              </lay-form-item>
            </lay-col>
          </lay-row>
          <lay-row space="10">
            <lay-col md="24" sm="24" xs="24">
              <lay-form-item label="id" prop="id" v-show="false">
                <lay-input v-model="model11.id" :disabled="true"></lay-input>
              </lay-form-item>
            </lay-col>
          </lay-row>
        </lay-form>
        <div style="width: 100%; text-align: center">
          <lay-button size="sm" type="primary" @click="toSubmit">保存</lay-button>
          <lay-button size="sm" @click="toCancel">取消</lay-button>
        </div>
      </div>
    </lay-layer>
    <!-- 关联角色 -->
    <lay-layer title="角色" :area="['80%', '100%']" v-model="visibleRole">
      <div style="padding: 20px">
        <lay-line theme="red">已赋予角色</lay-line>
        <lay-table :resize="true" :height="'100%'" :columns="columnsRole" :loading="loadingRole"
          :default-toolbar="false" :data-source="dataSourceRole" @sortChange="sortChangeRole"
          v-model:selected-keys="selectedKeysRoleV1">
        </lay-table>
        <div style="width: 100%; text-align: center;padding-top: 20px;">
          <lay-button size="sm" type="primary" @click="toCancelRelationship">取消角色</lay-button>
          <lay-button size="sm" @click="toCancelRole">关闭窗口</lay-button>
        </div>
        <lay-line theme="green" style="padding-top: 20px;">未赋予角色</lay-line>
        <lay-table :resize="true" :height="'100%'" :columns="columnsRole" :loading="loadingRole"
          :default-toolbar="false" :data-source="dataSourceRoleALL" v-model:selected-keys="selectedKeysRole">
        </lay-table>
        <div style="width: 100%; text-align: center;padding-top: 20px;">
          <lay-button size="sm" type="primary" @click="toSubmitRelationship">添加角色</lay-button>
          <lay-button size="sm" @click="toCancelRole">关闭窗口</lay-button>
        </div>
      </div>
    </lay-layer>
    <!-- 导入用户 -->
    <lay-layer v-model="visibleImport" title="导入用户" :area="['380px', '380px']">
      <lay-upload style="margin: 60px" :headers="Uploadheaders" :url="excelInputUrl" v-model="file1" field="file"
        :auto="true" :drag="true" @done="endingSucces">
        <template #preview>
          {{ file1[0]?.name }}
        </template>
      </lay-upload>
      <div style="width: 100%; text-align: center">
        只能上传小于1000KB的文件
      </div>
    </lay-layer>
  </lay-container>
</template>
<script setup lang="ts">
import { defineComponent, ref, reactive, onMounted } from 'vue'
import { layer } from '@layui/layui-vue'
import { getBaseUrl } from '../../../api/http'
import { useUserStore } from "../../../store/user";
import { listByLimit, saveBySuper, updateBySuper, delBySuper, delsBySuper, queryTree } from '../../../api/module/user'
import { queryForUserId, roleBindUser, roleBindUserRemove } from '../../../api/module/role-manager'

const searchQuery = ref({
  userName: '',
  nickName: '',
  sex: '',
  pageIndex: 1,
  pageSize: 10,
})
// 页面加载渲染
const loadingFlag = ref(true);

// 上传导入文件弹出的显示和隐藏
const visibleImport = ref(false)

const file1 = ref<any>([])

function endingSucces() {
  visibleImport.value = false;
  layer.msg('Success', { icon: 1, time: 2000 })
}
// 上传的Url
const excelInputUrl = ref<any>(null)

// 上传整体表单
const uploadRef = ref<any>(null)
const Uploadheaders = ref<any>(null)

// 上传请求
function handleUpload() {
  excelInputUrl.value = getBaseUrl() + "/sysUser/api/upload"
  uploadRef.value.submit()
}
// 导入按钮触发时事件
function toImport() {
  visibleImport.value = true
}

// 下载导入模板
function getImport() {
  const baseUrl = getBaseUrl();
  window.location.href = baseUrl + "/sysUser/api/modelDown"
}
function toReset() {
  searchQuery.value = {
    userName: '',
    nickName: '',
    sex: '',
    pageIndex: 1,
    pageSize: 10,
  }
  toSearch()
}
// 条件搜索调用
function toSearch() {
  page.current = 1
  setTimeout(() => {
    loadDataSource(page.current, page.limit)
  }, 1000)
}

// 表格的加载动画器
const loading = ref(false)
// 选中器--选中的数据
const selectedKeys = ref<string[]>([]);//ref([{}])

const page = reactive({ current: 1, limit: 10, total: 100 })
const columns = ref([
  { title: '选项', width: '60px', type: 'checkbox', fixed: 'left' },
  { title: '编号', width: '165px', key: 'id', fixed: 'left', sort: 'desc' },
  { title: '头像', width: '50px', key: 'avatar', customSlot: 'avatar' },
  { title: '姓名', width: '80px', key: 'nickName', sort: 'desc' },
  { title: '账号', width: '80px', key: 'userName', sort: 'desc' },
  { title: '状态', width: '80px', key: 'status', customSlot: 'status' },
  { title: '邮箱', width: '120px', key: 'email' },
  { title: '性别', width: '80px', key: 'sex' },
  { title: '签名', width: '160px', key: 'remark' },
  { title: '时间', width: '100px', key: 'updateTime' },
  {
    title: '操作',
    width: '120px',
    customSlot: 'operator',
    key: 'operator',
    fixed: 'right'
  }
])
// 部门选择器
const optionsDeptSelect = ref([]);

// 角色表格的加载动画器
const loadingRole = ref(false)

const visibleRole = ref(false)

function openRoleTableLar(row: any) {
  visibleRole.value = !visibleRole.value;
  // 加载数据
  loadDataSourceRole(row);
}

const currentRolebindUserId = ref('')
// 搜索渲染表格
const loadDataSourceRole = async (row: any) => {
  try {
    loadingRole.value = true;
    const userId = row.id;
    currentRolebindUserId.value = userId;
    const response = await queryForUserId(userId);
    // 重置表格的数据
    const list = response.data.currentLayer || [];
    const listNext = response.data.nextLayer || [];
    dataSourceRole.value = list;
    dataSourceRoleALL.value = listNext;
  } catch (error) {
    console.error('Error fetching data:', error);
  } finally {
    // 关闭数据加载渲染
    loadingRole.value = false;
  }
}

// 角色选中器--选中的数据
const selectedKeysRole = ref<string[]>([])
// 预备取消的角色
const selectedKeysRoleV1 = ref<string[]>([])
// 角色查看
const columnsRole = ref([
  { title: '选项', width: '60px', type: 'checkbox', fixed: 'left' },
  { title: '主键', width: '180px', key: 'id', fixed: 'left' },
  { title: '角色名称', width: '100px', key: 'roleName' },
  { title: '角色Key', width: '80px', key: 'roleKey' },
  { title: '显示顺序', width: '80px', key: 'roleSort' },
  { title: '状态', width: '80px', key: 'status' }
]);
// 提交取消关系
function toCancelRelationship() {
  const userId = currentRolebindUserId.value;
  const keyIndexs = selectedKeysRoleV1.value;
  let roleIds: any = [];
  keyIndexs.forEach(item => {
    const typeName = typeof item;
    if (typeName === 'string') {
      roleIds.push(item);
    }
  })
  if (roleIds.length === 0) {
    visibleRole.value = false;
    selectedKeysRoleV1.value = [];
    return false;
  }
  const requestBody = {
    "userId": userId,
    "roleIds": roleIds
  }
  roleBindUserRemove(requestBody).then(resp => {
    if (resp.success) {
      layer.msg('取消绑定成功' + resp.msg, { icon: 1, time: 2000 })
      visibleRole.value = false;
    } else {
      layer.msg('取消绑定失败' + resp.msg, { icon: 2, time: 2000 })
    }
    selectedKeysRoleV1.value = [];
  }).catch(err => {
    console.log("请求错误", err);
  });
}
// 提交追加关系
function toSubmitRelationship() {
  const userId = currentRolebindUserId.value;
  const keyIndexs = selectedKeysRole.value;
  let roleIds: any = [];
  keyIndexs.forEach(item => {
    const typeName = typeof item;
    if (typeName === 'string') {
      roleIds.push(item);
    }
  })
  if (roleIds.length === 0) {
    visibleRole.value = false;
    selectedKeysRole.value = [];
    return false;
  }
  const requestBody = {
    "userId": userId,
    "roleIds": roleIds
  }
  roleBindUser(requestBody).then(resp => {
    if (resp.success) {
      layer.msg('绑定成功' + resp.msg, { icon: 1, time: 2000 })
      visibleRole.value = false;
    } else {
      layer.msg('绑定失败' + resp.msg, { icon: 2, time: 2000 })
    }
    selectedKeysRole.value = [];
  }).catch(err => {
    console.log("请求错误", err);
  });

}
// 渲染数据列表集合{已赋予的角色}
const dataSourceRole = ref([{
  id: `1001`,
  roleName: 'Lay-vue-super',
  roleKey: 'super',
  roleSort: '1054769729@qq.com',
  status: true
}])

// 未赋予的角色
const dataSourceRoleALL = ref([{
  id: `1001`,
  roleName: 'Lay-vue-super',
  roleKey: 'super',
  roleSort: '1054769729@qq.com',
  status: true
}])

const changeRole = (page: any) => {
  loading.value = true
  setTimeout(() => {
    loadDataSource(page.current, page.limit)
    loading.value = false
  }, 1000)
}
const sortChangeRole = (key: any, sort: number) => {
  layer.msg(`字段${key} - 排序${sort}, 你可以利用 sort-change 实现服务端排序`)
}

const change = (page: any) => {
  loading.value = true
  setTimeout(() => {
    loadDataSource(page.current, page.limit)
    loading.value = false
  }, 1000)
}
const sortChange = (key: any, sort: number) => {
  layer.msg(`字段${key} - 排序${sort}, 你可以利用 sort-change 实现服务端排序`)
}


//模块加载完成---就执行
onMounted(() => {
  // 执行表格初始化渲染
  queryDataByServerForLimit()
  // 初始化上传的地址
  excelInputUrl.value = getBaseUrl() + "/sysUser/api/upload"
  // 初始胡设置Header 
  const userInfoStore = useUserStore();
  Uploadheaders.value = {
    token: userInfoStore.token,
    clientId: userInfoStore.clientId
  }
});

const optionsDeptSelectLoading = async (row: any) => {

  try {
    let userId = '';
    if (row) {
      userId = row.id;
    }
    const responBody = await queryTree(userId);
    // 重置表格的数据
    optionsDeptSelect.value = [];
    optionsDeptSelect.value = responBody.data.nextLayer;
    model11.value.deptId = responBody.data.currentLayer;
  } catch (error) {
    console.error('Error optionsDeptSelectLoading data:', error);
  }
}

// 获取接口用户信息
const queryDataByServerForLimit = async () => {
  try {
    const responBody = await listByLimit(searchQuery.value);
    // 重置表格的数据
    dataSource.value = [];
    dataSource.value = responBody.responseBody
    page.total = responBody.totalNum
    page.current = responBody.pageIndex
  } catch (error) {
    console.error('Error fetching data:', error);

  } finally {
    // 关闭数据加载渲染
    loadingFlag.value = false;
  }
}

// 渲染数据列表集合
const dataSource = ref([{
  id: `10011`,
  age: '28',
  sex: '男',
  avatar: 'https://foruda.gitee.com/avatar/1677022544584087390/4835367_jmysy_1578975358.png',
  name: `Lay-vue-super`,
  email: '1054769729@qq.com',
  remark: '海阔凭鱼跃,天高任鸟飞.',
  joinTime: '2024-12-09',
  city: '重庆北碚',
  status: true
}])

// 激活用户或者禁用用户
const changeStatus = (isChecked: boolean, row: any) => {
  const thatJson = {
    id: row.id,
    status: isChecked
  }
  updateBySuper(thatJson).then(resp => {
    if (resp.success) {
      dataSource.value.forEach((item) => {
        if (item.id === row.id) {
          layer.msg('Success', { icon: 1 }, () => {
            item.status = isChecked
          })
        }
      })
    } else {
      layer.msg('修改失败' + resp.msg, { icon: 2, time: 2000 })
    }
  })
}

const remove = () => {
  layer.msg(JSON.stringify(selectedKeys.value), { area: '50%' })
}

// 搜索渲染表格
const loadDataSource = async (pageIndex: number, pageSize: number) => {
  try {
    loading.value = true
    searchQuery.value.pageIndex = pageIndex
    searchQuery.value.pageSize = pageSize
    const response = await listByLimit(searchQuery.value);
    // 重置表格的数据
    const list = response.responseBody || [];
    dataSource.value = list;
    page.total = response.totalNum
    page.current = response.pageIndex
  } catch (error) {
    console.error('Error fetching data:', error);
  } finally {
    // 关闭数据加载渲染
    loading.value = false;
  }
}
// 新增区域
const model11 = ref<any>({})
// 弹出层表单数据
const layFormRef11 = ref()

// 编辑框是否展示
const visible11 = ref(false)

// 弹出层--标题
const title = ref('新增')

// 编辑回显
const editDataLoading = (text: any, row?: any) => {
  title.value = text
  if (row) {
    let info = JSON.parse(JSON.stringify(row))
    if (info.sex === '男') {
      info.sex = '0'
    } else {
      info.sex = '1'
    }
    model11.value = info
  } else {
    model11.value = {}
  }
  // 加载部门下拉框数据
  optionsDeptSelectLoading(row);

  visible11.value = !visible11.value;
}
// 清除校验
const clearValidate11 = function () {
  layFormRef11.value = {};
}
// 重置表单
const reset11 = function () {
  layFormRef11.value = {};
}
// 删除操作--需要二次确认
function toRemove() {
  if (selectedKeys.value.length == 0) {
    layer.msg('您未选择数据，请先选择要删除的数据', { icon: 3, time: 2000 })
    return false
  }
  const keyIndexs = selectedKeys.value;
  const dataItem = dataSource.value;
  layer.confirm('您将删除所有选中的数据？', {
    title: '提示',
    btn: [
      {
        text: '确定',
        // 这里回调的id和我们数据没有关系---是layer弹出层的
        callback: (id: any) => {
          let urlParams = "?";
          let arrayObj: any = []
          dataItem.forEach(itemObj => {
            keyIndexs.forEach(itemv2 => {
              if (itemObj.id === itemv2) {
                arrayObj.push("idList=" + itemObj.id)
              }
            })
          })
          urlParams = urlParams + arrayObj.join("&")
          delsBySuper(urlParams).then(resp => {
            if (resp.success) {
              layer.msg('执行成功！', { icon: 1, time: 1000 })
              // 重新渲染表格
              loadDataSource(page.current, page.limit)
            } else {
              layer.msg('保存失败' + resp.msg, { icon: 2, time: 2000 })
            }
          });
          layer.close(id)
        }
      },
      {
        text: '取消',
        callback: (id: any) => {
          layer.msg('您已取消操作')
          layer.close(id)
        }
      }
    ]
  })
}
// 保存用户信息
async function toSubmit() {
  try {
    const thatJson = model11.value;
    // 参数校验
    if (thatJson.nickName === "" || thatJson.nickName === undefined || thatJson.nickName === null) {
      layer.msg('用户名称未填写', { icon: 2, time: 2000 })
      return false;
    }
    if (thatJson.email === "" || thatJson.email === undefined || thatJson.email === null) {
      layer.msg('邮箱未填写', { icon: 2, time: 2000 })
      return false;
    }
    if (thatJson.phoneNumber === "" || thatJson.phoneNumber === undefined || thatJson.phoneNumber === null) {
      layer.msg('手机号未填写', { icon: 2, time: 2000 })
      return false;
    }
    if (title.value === '新增') {
      if (thatJson.password === "" || thatJson.password === undefined || thatJson.password === null) {
        layer.msg('密码未填写将使用', { icon: 2, time: 2000 })
        return false;
      }
    }
    let response;
    if (thatJson.id) {
      thatJson.loginIp = null
      thatJson.createTime = null
      thatJson.updateTime = null
      thatJson.userName = null
      response = await updateBySuper(thatJson);
    } else {
      response = await saveBySuper(thatJson);
    }
    if (response.success) {
      layer.msg('执行成功！', { icon: 1, time: 1000 })
      // 重新渲染表格
      loadDataSource(page.current, page.limit)
    } else {
      layer.msg('保存失败' + response.msg, { icon: 2, time: 2000 })
    }
    visible11.value = false
  } catch (error) {
    console.error('Error saving data:', error);
    layer.msg('保存失败: ' + (error || '未知错误'), { icon: 2, time: 2000 });
  }
}

function toCancel() {
  visible11.value = false
}

function toCancelRole() {
  visibleRole.value = false;
  selectedKeysRole.value = [];
}
// 删除操作提交
async function confirm(row: any) {
  const userId = row.id
  const response = await delBySuper(userId)
  if (response.success) {
    layer.msg('删除成功！', { icon: 1, time: 1000 })
    // 重新渲染表格
    loadDataSource(page.current, page.limit)
  } else {
    layer.msg('删除失败' + response.msg, { icon: 2, time: 2000 })
  }
}

function cancel() {
  layer.msg('您已取消操作')
}
const beforeUpload10 = (file: File) => {
  var isOver = false
  if (file.size > 1000) {
    isOver = true
    layer.msg(`file size over 1000 KB`, { icon: 2 })
  }
  return new Promise((resolver) => resolver(true))
}
</script>

<style scoped>
.user-box {
  height: calc(100vh - 110px);
  margin-top: 10px;
  box-sizing: border-box;
  overflow: hidden;
}

.top-search {
  margin-top: 10px;
  padding: 10px;
  height: 40px;
  border-radius: 4px;
  background-color: #fff;
}

.grid-demo {
  line-height: 50px;
  border-radius: 2px;
  text-align: center;
}

.table-box {
  margin-top: 10px;
  padding: 10px;
  height: 700px;
  width: 100%;
  border-radius: 4px;
  box-sizing: border-box;
  background-color: #fff;
}

.search-input {
  display: inline-block;
  width: 98%;
  margin-right: 10px;
}

.isChecked {
  display: inline-block;
  background-color: #e8f1ff;
  color: red;
}
</style>